home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / kernel / net / ds5000.md / netDF.c < prev    next >
C/C++ Source or Header  |  1992-12-18  |  48KB  |  1,693 lines

  1. /* 
  2.  * netDF.c --
  3.  *
  4.  *    The main routines for the device driver for the
  5.  *    DEC FDDI controller 700.
  6.  *
  7.  *
  8.  * Copyright 1992 Regents of the University of Californiaf
  9.  * Permission to use, copy, modify, and distribute this
  10.  * software and its documentation for any purpose and without
  11.  * fee is hereby granted, provided that the above copyright
  12.  * notice appear in all copies.  The University of California
  13.  * makes no representations about the suitability of this
  14.  * software for any purpose.  It is provided "as is" without
  15.  * express or implied warranty.
  16.  *
  17.  */
  18.  
  19. #ifndef lint
  20. static char rcsid[] = "$Header: /cdrom/src/kernel/Cvsroot/kernel/net/ds5000.md/netDF.c,v 1.4 92/07/17 17:25:10 jhh Exp $";
  21. #endif not lint
  22.  
  23. #include <sprite.h>
  24. #include <sys.h>
  25. #include <list.h>
  26. #include <netInt.h>
  27. #include <vm.h>
  28. #include <vmMach.h>
  29. #include <mach.h>
  30. #include <machMon.h>
  31. #include <dbg.h>
  32. #include <assert.h>
  33. #include <dev/fddi.h>
  34. #include <fmt.h>
  35. #include <netDFInt.h>
  36.  
  37. #ifdef sun4c
  38. #include <devSCSIC90.h>
  39. #endif
  40.  
  41. /*
  42.  * Macro to get the next descriptor on the COMMAND ring.
  43.  */
  44. #define    NEXT_CMD_DESC(p) ( (((p)+1) > statePtr->comLastPtr) ? \
  45.                 statePtr->comRingPtr : ((p)+1))
  46. /*
  47.  * Macro to access the buffer corresponding to the CMD descriptor.
  48.  */
  49. #define CmdBufFromDesc(statePtr, descPtr) \
  50.   (statePtr->comBufPtr + \
  51.   (NET_DF_COMMAND_BUF_SIZE * (unsigned long)(descPtr - statePtr->comRingPtr)))
  52.  
  53.  
  54. static void NetDFRestartCallback _ARGS_((ClientData data,
  55.                      Proc_CallInfo *infoPtr));
  56. /*
  57.  * Debug flag
  58.  */
  59. int netDFDebug;
  60.  
  61.  
  62. #ifdef NET_DF_USE_UNCACHED_MEM
  63.  
  64. NetDFState uncachedNetDFState[3];
  65.  
  66. #else
  67.  
  68. extern Net_Interface        *netInterfaces[NET_MAX_INTERFACES];
  69. extern int            netNumInterfaces;
  70.  
  71. #endif
  72.  
  73. void NetDFRestart();
  74.  
  75. /*
  76.  *----------------------------------------------------------------------
  77.  *
  78.  * NetDFPrintStateAddrs --
  79.  *
  80.  *    Print out the addresses of the NetDFState structs corresponding
  81.  *      to the FDDI interfaces.  Used for debugging only.
  82.  *
  83.  * Results:
  84.  *      None.
  85.  *
  86.  * Side effects:
  87.  *    Prints to stdout.
  88.  *
  89.  *----------------------------------------------------------------------
  90.  */
  91. void
  92. NetDFPrintStateAddrs()
  93. {
  94.     /*
  95.      * When the stack gets trashed, etc., it's hard to get a handle
  96.      * on the state structure being used.  So you can get the address
  97.      * in kgdb by calling this routine.
  98.      */
  99. #ifdef NET_DF_USE_UNCACHED_MEM
  100.     printf("slot 0: 0x%x\tslot 1: 0x%x\tslot 2: 0x%x\n",
  101.        &uncachedNetDFState[0], &uncachedNetDFState[1],
  102.        &uncachedNetDFState[2]);
  103. #else
  104.     int i;
  105.  
  106.     for (i = 0; i < netNumInterfaces; i++) {
  107.     if (netInterfaces[i]->netType == NET_NETWORK_FDDI) {
  108.         printf("slot %d: statePtr: 0x%x\n", 
  109.            netInterfaces[i]->unit, netInterfaces[i]->interfaceData);
  110.     }
  111.     }
  112. #endif
  113. }
  114.  
  115. /*
  116.  *----------------------------------------------------------------------
  117.  *
  118.  * NetDFInit --
  119.  *
  120.  *    Initialize the DEC FDDIcontroller 700 board.
  121.  *
  122.  * Results:
  123.  *    SUCCESS if the controller was found and initialized,
  124.  *    FAILURE otherwise.
  125.  *
  126.  * Side effects:
  127.  *    Initializes the NetDFState record, as well as the chip.
  128.  *
  129.  *----------------------------------------------------------------------
  130.  */
  131. ReturnStatus
  132. NetDFInit(interPtr)
  133.     Net_Interface    *interPtr;     /* Network interface. */
  134. {
  135.     register NetDFState        *statePtr;
  136.     List_Links                *itemPtr;
  137.     register int         i;
  138.     ReturnStatus            status;
  139.  
  140.     MASTER_LOCK(&interPtr->mutex)
  141.  
  142.     /*
  143.      * Just to make sure that the structures are the correct sizes.
  144.      */
  145.     assert(sizeof(Net_DFReg) == 2);
  146.     assert(sizeof(NetDFCommandDesc) == 16);
  147.     assert(sizeof(NetDFHostRcvDesc) == 16);
  148.     assert(sizeof(NetDFSmtRcvDesc) == 16);
  149.     assert(sizeof(NetDFSmtXmtDesc) == 16);
  150.     assert(sizeof(NetDFRmcXmtDesc) == 16);
  151.     assert(sizeof(NetDFUnsolDesc) == 16);
  152.  
  153.     netDFDebug = NET_DF_DEBUG_OFF;
  154.  
  155.     MAKE_NOTE("Initializing adapter.");
  156.  
  157. #ifdef NET_DF_USE_UNCACHED_MEM
  158.     statePtr = &uncachedNetDFState[(int)interPtr->ctrlAddr];
  159.     statePtr = (NetDFState *)MACH_UNCACHED_ADDR(statePtr);
  160. #else
  161.     statePtr = (NetDFState *) malloc (sizeof(NetDFState));
  162. #endif
  163.     bzero((char *) statePtr, sizeof(NetDFState)); 
  164.  
  165.     statePtr->running = FALSE;
  166.     status = NetDFMachInit(interPtr, statePtr);
  167.     if (status != SUCCESS) {
  168.     MASTER_UNLOCK(&interPtr->mutex);
  169. #ifndef NET_DF_USE_UNCACHED_MEM
  170.     free((char *) statePtr); 
  171. #endif
  172.     return status;
  173.     }
  174.  
  175.     /*
  176.      * Initialize the transmission list.  
  177.      */
  178.     statePtr->xmitList = &statePtr->xmitListHdr;
  179.     List_Init(statePtr->xmitList);
  180.     statePtr->xmitFreeList = &statePtr->xmitFreeListHdr;
  181.     List_Init(statePtr->xmitFreeList);
  182.  
  183.     for (i = 0; i < NET_DF_NUM_XMIT_ELEMENTS; i++) {
  184.     itemPtr = (List_Links *) malloc(sizeof(NetDFXmtElement)), 
  185.     List_InitElement(itemPtr);
  186.     List_Insert(itemPtr, LIST_ATREAR(statePtr->xmitFreeList));
  187.     }
  188.  
  189.     interPtr->init    = NetDFInit;
  190.     interPtr->output     = NetDFOutput;
  191.     interPtr->intr    = NetDFIntr;
  192.     interPtr->ioctl    = NetDFIOControl;
  193.     interPtr->reset     = Net_DFRestart;        /**/
  194.     interPtr->getStats    = NetDFGetStats;
  195.     interPtr->netType    = NET_NETWORK_FDDI;
  196.     interPtr->maxBytes    = NET_FDDI_MAX_BYTES - sizeof(Net_FDDIHdr);
  197.     interPtr->minBytes    = NET_FDDI_MIN_BYTES;
  198.     interPtr->interfaceData = (ClientData) statePtr;
  199.  
  200.     statePtr->interPtr = interPtr;
  201.     statePtr->recvMemInitialized = FALSE;
  202.     statePtr->recvMemAllocated = FALSE;
  203.     statePtr->xmitMemInitialized = FALSE;
  204.     statePtr->xmitMemAllocated = FALSE;
  205.     statePtr->resetPending = FALSE;
  206.     statePtr->curScatGathPtr = (Net_ScatterGather *) NIL;
  207.  
  208.     /*
  209.      * Initialize buffer for storing the results of an INIT command.
  210.      * These results will later be used by a PARAM command.
  211.      */
  212.     statePtr->initComPtr = (NetDFInitCommand *)malloc(NET_DF_COMMAND_BUF_SIZE);
  213.  
  214.     /*
  215.      * Reset the world.  
  216.      */
  217.     NetDFReset(interPtr);
  218.  
  219.  
  220.     /*
  221.      * Now we are running.
  222.      */
  223.     statePtr->running = TRUE;
  224.     statePtr->flags = NET_DF_FLAGS_NORMAL;
  225.  
  226.     MASTER_UNLOCK(&interPtr->mutex);
  227.  
  228.     return (SUCCESS); 
  229. }
  230.  
  231. /*
  232.  * Simple debug ring to hold strings.
  233.  */
  234. char *netDFDebugRing[NET_DF_DEBUG_RING_SIZE];
  235. int  netDFDebugRingIndex;
  236.  
  237.  
  238.  
  239. /*
  240.  *----------------------------------------------------------------------
  241.  *
  242.  * NetDFPrintDebugRing --
  243.  *
  244.  *    Print out the contents of the debug ring, from most remote to
  245.  *      most recent in time.
  246.  *
  247.  * Results:
  248.  *    None.
  249.  *
  250.  * Side effects:
  251.  *    Debug messages are printed.
  252.  *
  253.  *----------------------------------------------------------------------
  254.  */
  255. /*ARGSUSED*/
  256. void
  257. NetDFPrintDebugRing(statePtr)
  258.     register NetDFState *statePtr;
  259. {
  260.     char *messagePtr;
  261.     int  index;
  262.     
  263.     index = netDFDebugRingIndex;
  264.  
  265.     printf("<---\n");
  266.     while (TRUE) {
  267.     /*
  268.      * Start at the last one.
  269.      */
  270.     messagePtr = netDFDebugRing[index];
  271.     if (messagePtr !=  NULL) {
  272.         printf("%d\t%s\n", index, messagePtr);
  273.     }
  274.     index = (index + 1) % NET_DF_DEBUG_RING_SIZE;
  275.     if (index == netDFDebugRingIndex) {
  276.         break;
  277.     }
  278.     }
  279.     printf("--->\n");
  280. }
  281.  
  282. /*
  283.  *----------------------------------------------------------------------
  284.  *
  285.  * NetDFPrintRegContents --
  286.  *
  287.  *    Print out the contents in each of the six registers on the adapter.
  288.  *
  289.  * Results:
  290.  *    None.
  291.  *
  292.  * Side effects:
  293.  *    The register contents are printed.
  294.  *
  295.  *----------------------------------------------------------------------
  296.  */
  297. void
  298. NetDFPrintRegContents(statePtr)
  299.     register NetDFState *statePtr;
  300. {
  301.     register unsigned short status;
  302.  
  303.     status = *(statePtr->regReset);
  304.     printf("Reset: 0x%x\t", status);
  305.     status = *(statePtr->regCtrlA);
  306.     printf("CtrlA: 0x%x\t", status);
  307.     status = *(statePtr->regCtrlB);
  308.     printf("CtrlB: 0x%x\n", status);
  309.     status = *(statePtr->regStatus);
  310.     printf("Status: 0x%x\t", status);
  311.     status = *(statePtr->regEvent);
  312.     printf("Event: 0x%x\t", status);
  313.     status = *(statePtr->regMask);
  314.     printf("Mask: 0x%x\n", status);
  315. }
  316.  
  317. /*
  318.  *----------------------------------------------------------------------
  319.  *
  320.  * NetDFPrintErrLog --
  321.  *
  322.  *    Print out selected contents of the error log.  Error codes
  323.  *      are placed in a log buffer on the adapter when the
  324.  *      adapter goes wacky.
  325.  *
  326.  * Results:
  327.  *    None.
  328.  *
  329.  * Side effects:
  330.  *    Error log contents are printed.
  331.  *
  332.  *----------------------------------------------------------------------
  333.  */
  334. void
  335. NetDFPrintErrorLog(statePtr)
  336.     register NetDFState *statePtr;
  337. {
  338.     register volatile unsigned char  *errPtr;
  339.     register unsigned long           large;
  340.  
  341.     /*
  342.      * The internal code specifies a more detailed error than the
  343.      * external code.
  344.      */
  345.     errPtr = statePtr->errLogPtr;
  346.     large = (unsigned long)*(errPtr + NET_DF_MACH_ERR_INTERNAL_OFFSET);
  347.     /*
  348.      * The external code is the one that can be found in the STATUS
  349.      * regsiter.
  350.      */
  351.     printf("Internal: 0x%x\t", large);
  352.     large = (unsigned long)*(errPtr + NET_DF_MACH_ERR_EXTERNAL_OFFSET);
  353.     printf("External: 0x%x\t", large);
  354. }
  355.  
  356. /*
  357.  *----------------------------------------------------------------------
  358.  *
  359.  * NetDFAssertState --
  360.  *
  361.  *    If the adapter is not in the given state, then panic!
  362.  *
  363.  * Results:
  364.  *    None.
  365.  *
  366.  * Side effects:
  367.  *    We could panic.
  368.  *
  369.  *----------------------------------------------------------------------
  370.  */
  371. void
  372. NetDFAssertState(statePtr, state)
  373.     register NetDFState *statePtr;
  374.     unsigned short state; 
  375. {
  376.     unsigned short  status;
  377.     
  378.     status = *(statePtr->regStatus) & NET_DF_STATUS_ADAPTER_STATE;
  379.     if (status != state) {
  380.     status = status;
  381.     panic("DEC FDDI: adapter in wrong state (is %x, want %x)\n", 
  382.           status, state);
  383.     }
  384. }
  385.  
  386. /*
  387.  *----------------------------------------------------------------------
  388.  *
  389.  * NetDFCommandTimeout --
  390.  *
  391.  *    Wait for a command to finish.  If it does not finish within
  392.  *      a finite time, then stop waiting and return an error.
  393.  *
  394.  * Results:
  395.  *    SUCCESS if the command finished within its allotted time,
  396.  *      and FAILURE otherwise.
  397.  *
  398.  * Side effects:
  399.  *    None.
  400.  *
  401.  *----------------------------------------------------------------------
  402.  */
  403. ReturnStatus
  404. NetDFCommandTimeout(statePtr, comDescPtr)
  405.     register NetDFState                *statePtr;
  406.     register volatile NetDFCommandDesc *comDescPtr;
  407. {
  408.     register volatile Net_DFReg status;
  409.     register volatile Net_DFReg event;
  410.     register unsigned long      n;
  411.  
  412.     /*
  413.      * Clear the CMD_DONE bit, and give ownership of the command descriptor to
  414.      * the adapter.  Then poke the CTRLA register, telling it that we've set
  415.      * up a command to be executed.
  416.      */
  417.     *(statePtr->regEvent) = NET_DF_EVENT_CMD_DONE;
  418.     n = comDescPtr->command & NET_DF_COMMAND_MASK;
  419.     comDescPtr->command = n | NET_DF_ADAPTER_OWN;
  420.     *(statePtr->regCtrlA) |= NET_DF_CTRLA_CMD_POLL_DEMAND;
  421.  
  422.     /*
  423.      * Wait for the CMD_DONE event.
  424.      */
  425.     status = FAILURE;
  426.     for (n = 0; n < 10000000; n++) {
  427.     event = *(statePtr->regEvent);
  428.     if (event & NET_DF_EVENT_CMD_DONE) {
  429.         /*
  430.          * Clear the event we just noticed
  431.          */
  432.         *(statePtr->regEvent) = NET_DF_EVENT_CMD_DONE;
  433.         status = SUCCESS;
  434.         break;
  435.     }
  436.     }
  437.  
  438.     if (status == SUCCESS && comDescPtr->status == NET_DF_COMMAND_STATUS_OK) {
  439.     return status;
  440.     }
  441.     NetDFPrintRegContents(statePtr);
  442.     NetDFPrintErrorLog(statePtr);
  443.     if (status == SUCCESS) {
  444.     printf("DEC FDDI: command %d did not work\n", 
  445.            comDescPtr->command & NET_DF_COMMAND_MASK);
  446.     } else {
  447.     printf("DEC FDDI: command %d timed out\n", 
  448.            comDescPtr->command & NET_DF_COMMAND_MASK);
  449.     }
  450.     printf("command addr: 0x%x\n", comDescPtr);
  451.     printf("command status: 0x%x\n", comDescPtr->status);
  452.     printf("command field: 0x%x\n", comDescPtr->command);
  453.     printf("bufAddr field: 0x%x\n", comDescPtr->bufAddr);
  454.     return FAILURE;
  455. }
  456.  
  457. /*
  458.  *----------------------------------------------------------------------
  459.  *
  460.  * NetDFDoInitCommand --
  461.  *
  462.  *    Execute the INIT command on the DEC FDDI adapter.
  463.  *
  464.  * Results:
  465.  *    SUCCESS if the INIT command succeeded, FAILURE otherwise.
  466.  *
  467.  * Side effects:
  468.  *    If successful, the adapter will transition to the INITIALIZED
  469.  *      state, and the interface will have its pointers updated with
  470.  *      the base addresses for the adapter rings and the link address
  471.  *      for the adapter.  The link address is reported to the console.
  472.  *
  473.  *----------------------------------------------------------------------
  474.  */
  475. ReturnStatus
  476. NetDFDoInitCommand(statePtr)
  477.     register NetDFState         *statePtr; /* Interface to FDDI adapter. */
  478. {
  479.     register volatile NetDFInitCommand   *comInitPtr;
  480.     register volatile NetDFCommandDesc   *comDescPtr;
  481.     register char                        *linkAddr;
  482.     register char                        *slotAddr;
  483.     register int             i;
  484.     int                                  slot;
  485.     Mach_SlotInfo                        slotInfo;
  486.     char                                 buffer[32];
  487.     ReturnStatus                         result;
  488.  
  489.     /*
  490.      * The adapter must be in the UNINITIALIZED state.
  491.      */
  492.     NetDFAssertState(statePtr, NET_DF_STATE_UNINITIALIZED);
  493.  
  494.     comDescPtr = statePtr->comNextPtr;
  495.     if ((comDescPtr->command & NET_DF_OWN) == NET_DF_ADAPTER_OWN) {
  496.     panic("DEC FDDI: Command Descriptor owned by adapter!");
  497.     }
  498.     statePtr->comNextPtr = NEXT_CMD_DESC(comDescPtr);
  499.     comInitPtr = (NetDFInitCommand *)CmdBufFromDesc(statePtr, comDescPtr);
  500.     /*
  501.      * Set up a command descriptor for an INIT command.
  502.      */
  503.     comDescPtr->command = NET_DF_HOST_OWN | NET_DF_COMMAND_INIT;
  504.     comDescPtr->status = 0x0;
  505.     comDescPtr->bufAddr = (NET_DF_ULONG)comInitPtr;
  506.  
  507.     /*
  508.      * Set up the command buffer with proper input values.
  509.      */
  510.     bzero((Address)comInitPtr, NET_DF_COMMAND_BUF_SIZE);
  511.     comInitPtr->transmitMode = NET_DF_INIT_TRANSMIT_MODE;
  512.     comInitPtr->rcvEntries = NET_DF_INIT_HOST_RCV_ENTRIES;
  513.     Mach_EmptyWriteBuffer();
  514.  
  515.     result = NetDFCommandTimeout(statePtr, comDescPtr);
  516.     if (result != SUCCESS) {
  517.     panic("DEC FDDI: INIT command failed!\n");
  518.     }
  519.  
  520.     /*
  521.      * We should have transitioned into the INITIALIZED state.
  522.      * Clear the STATE_CHANGE event bit.
  523.      */
  524.     NetDFAssertState(statePtr, NET_DF_STATE_INITIALIZED);
  525.     *(statePtr->regEvent) = NET_DF_EVENT_STATE_CHANGE;
  526.  
  527.     /*
  528.      * Extract and report the FDDI address.
  529.      */
  530.     linkAddr = (char *)comInitPtr->linkAddress;
  531.     for (i = 0; i < 6; i++) {
  532.     ((char *)&statePtr->fddiAddress)[i] = linkAddr[i];
  533.     }
  534.  
  535.     slot = (int) statePtr->interPtr->ctrlAddr;
  536.     slotAddr = statePtr->slotAddr;
  537.     result = Mach_GetSlotInfo(slotAddr + NET_DF_MACH_OPTION_ROM_OFFSET, 
  538.                   &slotInfo);
  539.     if (result != SUCCESS) {
  540.     return result;
  541.     }
  542.     (void) Net_FDDIAddrToString(&statePtr->fddiAddress, buffer);
  543.     printf("FDDI in slot %d, address %s (%s %s %s %s)\n",
  544.        slot, buffer, slotInfo.module, slotInfo.vendor, 
  545.        slotInfo.revision, slotInfo.type);
  546.     result = Net_SetAddress(NET_ADDRESS_FDDI, 
  547.         (Address) &statePtr->fddiAddress,
  548.         &statePtr->interPtr->netAddress[NET_PROTO_RAW]);
  549.     if (result != SUCCESS) {
  550.     panic("NetDFDoInitCommand: Net_SetAddress failed.\n");
  551.     }
  552.     /*
  553.      * Save the INIT command buffer...we will need its values for
  554.      * the PARAM command that gets done a little later.  After the command
  555.      * ring goes around once, this buffer becomes invalid.
  556.      */
  557.     bcopy(comInitPtr, statePtr->initComPtr, NET_DF_COMMAND_BUF_SIZE);
  558.  
  559.     return SUCCESS;
  560. }
  561.  
  562. /*
  563.  *----------------------------------------------------------------------
  564.  *
  565.  * NetDFDoModcamCommand --
  566.  *
  567.  *    Execute the MODCAM command on the DEC FDDI adapter.
  568.  *
  569.  * Results:
  570.  *    SUCCESS if the MODCAM command succeeded, FAILURE otherwise.
  571.  *
  572.  * Side effects:
  573.  *    If successful, the adapter will be loaded with the default
  574.  *      CAM entries for address recognition (i.e.,
  575.  *      NET_DF_MODCAM_RING_PURGE, NET_DF_MODCAM_BEACON)
  576.  *
  577.  *----------------------------------------------------------------------
  578.  */
  579. ReturnStatus
  580. NetDFDoModcamCommand(statePtr)
  581.     register NetDFState         *statePtr; /* Interface to FDDI adapter. */
  582. {
  583.     register volatile NetDFModcamCommand *comModcamPtr;
  584.     register volatile NetDFCommandDesc   *comDescPtr;
  585.     register unsigned long               *intAddr;
  586.     ReturnStatus                         result;
  587.  
  588.     comDescPtr = statePtr->comNextPtr;
  589.     if ((comDescPtr->command & NET_DF_OWN) == NET_DF_ADAPTER_OWN) {
  590.     panic("DEC FDDI: Command Descriptor owned by adapter!");
  591.     }
  592.     statePtr->comNextPtr = NEXT_CMD_DESC(comDescPtr);
  593.     comModcamPtr = (NetDFModcamCommand *)CmdBufFromDesc(statePtr, comDescPtr);
  594.     /*
  595.      * Set up a command descriptor for a MODCAM command.
  596.      */
  597.     comDescPtr->command = NET_DF_HOST_OWN | NET_DF_COMMAND_MODCAM;
  598.     comDescPtr->status = 0x0;
  599.     comDescPtr->bufAddr = (NET_DF_ULONG)comModcamPtr;
  600.  
  601.     /*
  602.      * Set up the command buffer with proper input values.
  603.      */
  604.     bzero((Address)comModcamPtr, NET_DF_COMMAND_BUF_SIZE);
  605.  
  606.     intAddr = (unsigned long *)comModcamPtr;
  607.     intAddr[0] = NET_DF_MODCAM_BEACON_LOW;
  608.     intAddr[1] = NET_DF_MODCAM_BEACON_HIGH;
  609.     intAddr[2] = NET_DF_MODCAM_RING_PURGE_LOW;
  610.     intAddr[3] = NET_DF_MODCAM_RING_PURGE_HIGH;
  611.     Mach_EmptyWriteBuffer();
  612.  
  613.     result = NetDFCommandTimeout(statePtr, comDescPtr);
  614.     if (result != SUCCESS) {
  615.     printf("DEC FDDI: MODCAM command did not work!\n");
  616.     }
  617.     return result;
  618. }
  619.  
  620. /*
  621.  *----------------------------------------------------------------------
  622.  *
  623.  * NetDFDoStatusCommand --
  624.  *
  625.  *    Execute the STATUS command on the DEC FDDI adapter. 
  626.  *
  627.  * Results:
  628.  *    SUCCESS if the STATUS command succeeded, FAILURE otherwise.
  629.  *
  630.  * Side effects:
  631.  *      The statusComPtr slot of the statePtr is updated with the
  632.  *      results of the status command.
  633.  *
  634.  *----------------------------------------------------------------------
  635.  */
  636. ReturnStatus
  637. NetDFDoStatusCommand(statePtr)
  638.     register NetDFState         *statePtr; /* Interface to FDDI adapter. */
  639. {
  640.     register volatile NetDFStatusCommand *comStatusPtr;
  641.     register volatile NetDFCommandDesc   *comDescPtr;
  642.     ReturnStatus                         result;
  643.  
  644.     comDescPtr = statePtr->comNextPtr;
  645.     if ((comDescPtr->command & NET_DF_OWN) == NET_DF_ADAPTER_OWN) {
  646.     panic("DEC FDDI: Command Descriptor owned by adapter!");
  647.     }
  648.     statePtr->comNextPtr = NEXT_CMD_DESC(comDescPtr);
  649.     comStatusPtr = (NetDFStatusCommand *)CmdBufFromDesc(statePtr, comDescPtr);
  650.     /*
  651.      * Set up a command descriptor for a STATUS command.
  652.      */
  653.     comDescPtr->command = NET_DF_HOST_OWN | NET_DF_COMMAND_STATUS;
  654.     comDescPtr->status = 0x0;
  655.     comDescPtr->bufAddr = (NET_DF_ULONG)comStatusPtr;
  656.     
  657.     /*
  658.      * Set up the command buffer with proper input values.
  659.      * For a status command, the adapter fills it all in.
  660.      */
  661.     bzero((Address)comStatusPtr, NET_DF_COMMAND_BUF_SIZE);
  662.     Mach_EmptyWriteBuffer();
  663.  
  664.     result = NetDFCommandTimeout(statePtr, comDescPtr);
  665.     if (result != SUCCESS) {
  666.     printf("DEC FDDI: STATUS command did not work, darnit!\n");
  667.     return FAILURE;
  668.     } 
  669.     
  670.     printf("LED state 0x%x\t", comStatusPtr->ledState);
  671.     printf("Link state 0x%x\t", comStatusPtr->linkState);
  672.     printf("Phy state 0x%x\n", comStatusPtr->phyState);
  673.     return SUCCESS;
  674. }
  675.  
  676. /*
  677.  *----------------------------------------------------------------------
  678.  *
  679.  * NetDFDoRdcamCommand --
  680.  *
  681.  *    Execute the RDCAM command on the DEC FDDI adapter.
  682.  *
  683.  * Results:
  684.  *    SUCCESS if the RDCAM command succeeded, FAILURE otherwise.
  685.  *
  686.  * Side effects:
  687.  *
  688.  *----------------------------------------------------------------------
  689.  */
  690. ReturnStatus
  691. NetDFDoRdcamCommand(statePtr)
  692.     register NetDFState                *statePtr;
  693. {
  694.     register volatile NetDFRdcamCommand  *comRdcamPtr;
  695.     register volatile NetDFCommandDesc   *comDescPtr;
  696.     register int             j, k;
  697.     register char                        *addr;
  698.     char                                 buffer[32];
  699.     Net_FDDIAddress                      fddiAddress;
  700.     ReturnStatus                         result;
  701.  
  702.     comDescPtr = statePtr->comNextPtr;
  703.     if ((comDescPtr->command & NET_DF_OWN) == NET_DF_ADAPTER_OWN) {
  704.     panic("DEC FDDI: Command Descriptor owned by adapter!");
  705.     }
  706.     statePtr->comNextPtr = NEXT_CMD_DESC(comDescPtr);
  707.     comRdcamPtr = (NetDFRdcamCommand *)CmdBufFromDesc(statePtr, comDescPtr);
  708.     /*
  709.      * Set up a command descriptor for a RDCAM command.
  710.      */
  711.     comDescPtr->command = NET_DF_HOST_OWN | NET_DF_COMMAND_RDCAM;
  712.     comDescPtr->status = 0x0;
  713.     comDescPtr->bufAddr = (NET_DF_ULONG)comRdcamPtr;
  714.     
  715.     /*
  716.      * Set up the command buffer with proper input values.
  717.      */
  718.     bzero((Address)comRdcamPtr, NET_DF_COMMAND_BUF_SIZE);
  719.     Mach_EmptyWriteBuffer();
  720.  
  721.     result = NetDFCommandTimeout(statePtr, comDescPtr);
  722.     if (result != SUCCESS) {
  723.     printf("DEC FDDI: shoot! the RDCAM command did not work!\n");
  724.     return result;
  725.     }
  726.     /*
  727.      * Print out the addresses returned in the buffer.
  728.      */
  729.     for (j = 0; j < 2; j++) {
  730.     addr = (char *)(comRdcamPtr + j);
  731.     for (k = 0; k < 6; k++) {
  732.         ((char *)&fddiAddress)[k] = addr[k];
  733.     }
  734.     (void) Net_FDDIAddrToString(&fddiAddress, buffer);
  735.     DFprintf("RDCAM entry %d addr 0x%x -- %s\n", j, 
  736.            comRdcamPtr + j, buffer);
  737.     }
  738.     return SUCCESS;
  739. }
  740.  
  741. /*
  742.  *----------------------------------------------------------------------
  743.  *
  744.  * NetDFDoParamCommand --
  745.  *
  746.  *    Execute the PARAM command on the DEC FDDI adapter.
  747.  *
  748.  * Results:
  749.  *    SUCCESS if the PARAM command succeeded, FAILURE otherwise.
  750.  *
  751.  * Side effects:
  752.  *    If successful, the adapter will transition to the RUNNING state
  753.  *      and connect to the FDDI ring.  Processing of receive and
  754.  *      transmit frames will begin.
  755.  *
  756.  *----------------------------------------------------------------------
  757.  */
  758. ReturnStatus
  759. NetDFDoParamCommand(statePtr)
  760.     register NetDFState      *statePtr; /* Interface to FDDI adapter. */
  761. {
  762.     register volatile NetDFParamCommand  *comParamPtr;
  763.     register volatile NetDFCommandDesc   *comDescPtr;
  764.     ReturnStatus                         result;
  765.  
  766.     comDescPtr = statePtr->comNextPtr;
  767.     if ((comDescPtr->command & NET_DF_OWN) == NET_DF_ADAPTER_OWN) {
  768.     panic("DEC FDDI: Command Descriptor owned by adapter!");
  769.     }
  770.     statePtr->comNextPtr = NEXT_CMD_DESC(comDescPtr);
  771.     comParamPtr = (NetDFParamCommand *)CmdBufFromDesc(statePtr, comDescPtr);
  772.     /*
  773.      * Set up a command descriptor for a PARAM command.
  774.      */
  775.     comDescPtr->command = NET_DF_HOST_OWN | NET_DF_COMMAND_PARAM;
  776.     comDescPtr->status = 0x0;
  777.     comDescPtr->bufAddr = (NET_DF_ULONG)comParamPtr;
  778.     
  779.     /*
  780.      * Set up the command buffer with proper input values.
  781.      * Most of these values are default values that are given
  782.      * to us from the adapter using the INIT command.
  783.      */
  784.     bzero((Address)comParamPtr, NET_DF_COMMAND_BUF_SIZE);
  785.     comParamPtr->loopMode = NET_DF_NO_LOOP;
  786.     comParamPtr->tMax = statePtr->initComPtr->defaultTMax;
  787.     comParamPtr->tReq = statePtr->initComPtr->defaultTReq;
  788.     comParamPtr->tvx = statePtr->initComPtr->defaultTvx;
  789.     comParamPtr->lemThresh = statePtr->initComPtr->lemThresh;
  790.     comParamPtr->stationID.count1 = statePtr->initComPtr->stationID.count1;
  791.     comParamPtr->stationID.count2 = statePtr->initComPtr->stationID.count2;
  792.     comParamPtr->tokenTimeout =    statePtr->initComPtr->tokenTimeout;
  793.     comParamPtr->ringPurgeEnable = statePtr->initComPtr->ringPurgeEnable;
  794.     Mach_EmptyWriteBuffer();
  795.  
  796.     result = NetDFCommandTimeout(statePtr, comDescPtr);
  797.     if (result != SUCCESS) {
  798.     printf("DEC FDDI: uh oh...the PARAM command did not work\n");
  799.     return result;
  800.     }
  801.     /*
  802.      * We should have transitioned into the RUNNING state.
  803.      * Make sure to clear the STATE_CHANGE event bit.
  804.      */
  805.     NetDFAssertState(statePtr, NET_DF_STATE_RUNNING);
  806.     *(statePtr->regEvent) = NET_DF_EVENT_STATE_CHANGE;
  807.     return SUCCESS;
  808. }
  809.  
  810. /*
  811.  *----------------------------------------------------------------------
  812.  *
  813.  * NetDFDoModpromCommand --
  814.  *
  815.  *    Execute the MODPROM command on the DEC FDDI adapter.
  816.  *
  817.  * Results:
  818.  *    SUCCESS if the MODPROM command succeeded, FAILURE otherwise.
  819.  *
  820.  * Side effects:
  821.  *
  822.  *----------------------------------------------------------------------
  823.  */
  824. ReturnStatus
  825. NetDFDoModpromCommand(statePtr)
  826.     register NetDFState                *statePtr; 
  827. {
  828.     register volatile NetDFModpromCommand *comModpromPtr;
  829.     register volatile NetDFCommandDesc    *comDescPtr;
  830.     ReturnStatus                          result;
  831.  
  832.     comDescPtr = statePtr->comNextPtr;
  833.     if ((comDescPtr->command & NET_DF_OWN) == NET_DF_ADAPTER_OWN) {
  834.     panic("DEC FDDI: Command Descriptor owned by adapter!");
  835.     }
  836.     statePtr->comNextPtr = NEXT_CMD_DESC(comDescPtr);
  837.     comModpromPtr = (NetDFModpromCommand *)
  838.     CmdBufFromDesc(statePtr, comDescPtr);
  839.     /*
  840.      * Set up a command descriptor for a MODPROM command.
  841.      */
  842.     comDescPtr->command = NET_DF_HOST_OWN | NET_DF_COMMAND_MODPROM;
  843.     comDescPtr->status = 0x0;
  844.     comDescPtr->bufAddr = (NET_DF_ULONG)comModpromPtr;
  845.     
  846.     /*
  847.      * Set up the command buffer with proper input values.
  848.      */
  849.     bzero((Address)comModpromPtr, NET_DF_COMMAND_BUF_SIZE);
  850.  
  851.     comModpromPtr->llcPromEnable = NET_DF_FALSE;
  852.     comModpromPtr->smtPromEnable = NET_DF_FALSE;
  853.     comModpromPtr->llcMultiEnable = NET_DF_FALSE;
  854.     comModpromPtr->llcBroadEnable = NET_DF_FALSE;
  855.  
  856.     result = NetDFCommandTimeout(statePtr, comDescPtr);
  857.     if (result != SUCCESS) {
  858.     printf("DEC FDDI: MODPROM command didn't work\n");
  859.     return FAILURE;
  860.     }
  861.     return SUCCESS;
  862. }
  863.  
  864. /*
  865.  *----------------------------------------------------------------------
  866.  *
  867.  * ProcessUnsolicited --
  868.  *
  869.  *    Process the UNSOLICITED ring entries.  We just report
  870.  *      what they say;  we don't really act on them.
  871.  *
  872.  * Results:
  873.  *    SUCCESS if we succeeded to read them, FAILURE otherwise.
  874.  *
  875.  * Side effects:
  876.  *
  877.  *----------------------------------------------------------------------
  878.  */
  879. static ReturnStatus
  880. ProcessUnsolicited(statePtr)
  881.     register NetDFState *statePtr;
  882. {
  883.     register volatile NetDFUnsolDesc  *descPtr;
  884.     register Net_FDDIAddress          *addrPtr;
  885.     register NetDFDirectedBeacon      *beaconPtr;
  886.     char                              buffer[32];
  887.  
  888.     static char     *eventNames[] = {
  889.     "UNDEFINED",
  890.     "RING_INIT_INIT",
  891.     "RING_INIT_RCV",
  892.     "BEACON_INIT",
  893.     "DUP_ADDR",
  894.     "DUP_TOKEN",
  895.     "PURGE_ERROR",
  896.     "STRIP_ERROR",
  897.     "OP_OSCILLAT",
  898.     "BEACON_RCV",
  899.     "PC_TRACE_INIT",
  900.     "PC_TRACE_RECV",
  901.     "XMT_UNDERRUN",
  902.     "XMT_FAILURE",
  903.     "RCV_OVERRUN"
  904.     };
  905.     
  906.     descPtr = statePtr->unsolNextDescPtr;
  907.     
  908.     if ((descPtr->own & NET_DF_OWN) == NET_DF_ADAPTER_OWN) {
  909.     if (statePtr->lastUnsolCnt == 0) {
  910.         printf("DEC FDDI: Unsolicited Descriptor owned by adapter.\n");
  911.         return (FAILURE);
  912.     } else {
  913.         statePtr->lastUnsolCnt == 0;
  914.         return (SUCCESS);
  915.     }
  916.     }
  917.     statePtr->lastUnsolCnt = 0;
  918.     while (TRUE) {
  919.     switch ((int) descPtr->eventID) {
  920.     case NET_DF_UNSOL_UNDEFINED:
  921.     case NET_DF_UNSOL_RING_INIT_INIT:
  922.     case NET_DF_UNSOL_RING_INIT_RCV:
  923.     case NET_DF_UNSOL_BEACON_INIT:
  924.     case NET_DF_UNSOL_DUP_ADDR:
  925.     case NET_DF_UNSOL_DUP_TOKEN:
  926.     case NET_DF_UNSOL_PURGE_ERROR:
  927.     case NET_DF_UNSOL_STRIP_ERROR:
  928.     case NET_DF_UNSOL_OP_OSCILLAT:
  929.     case NET_DF_UNSOL_PC_TRACE_INIT:
  930.     case NET_DF_UNSOL_PC_TRACE_RECV:
  931.     case NET_DF_UNSOL_XMT_UNDERRUN:
  932.     case NET_DF_UNSOL_XMT_FAILURE:
  933.     case NET_DF_UNSOL_RCV_OVERRUN:
  934.         printf("DEC FDDI: Received Unsolicited Event: %s\n", 
  935.            eventNames[descPtr->eventID]);
  936.         break;
  937.     case NET_DF_UNSOL_BEACON_RCV:
  938.         printf("DEC FDDI: Received Unsolicited Event: %s\n", 
  939.            eventNames[descPtr->eventID]);
  940.         beaconPtr = (NetDFDirectedBeacon *)
  941.         (descPtr->bufAddr + statePtr->slotAddr);
  942.         addrPtr = (Net_FDDIAddress *)beaconPtr->sourceAddr;
  943.         (void) Net_FDDIAddrToString(addrPtr, buffer);
  944.         printf("          Source Address: %s", buffer);
  945.         addrPtr = (Net_FDDIAddress *)beaconPtr->una;
  946.         (void) Net_FDDIAddrToString(addrPtr, buffer);
  947.         printf("          UNA of Source: %s", buffer);
  948.  
  949.         break;
  950.     default:
  951.         printf("DEC FDDI: Unknown Unsolicited Event.\n");
  952.         break;
  953.     }
  954.     statePtr->lastUnsolCnt++;
  955.     descPtr = (descPtr + 1) > statePtr->unsolLastDescPtr ?
  956.         statePtr->unsolFirstDescPtr : (descPtr + 1);
  957.     if ((descPtr->own & NET_DF_OWN) == NET_DF_ADAPTER_OWN) {
  958.         break;
  959.     }
  960.     }
  961.     statePtr->unsolNextDescPtr = descPtr;
  962.     return (SUCCESS);
  963. }
  964.  
  965. static void FinishReset();
  966.  
  967.  
  968. /*
  969.  *----------------------------------------------------------------------
  970.  *
  971.  * NetDFReset --
  972.  *
  973.  *    Reset the interface.
  974.  *
  975.  * Results:
  976.  *    None.
  977.  *
  978.  * Side effects:
  979.  *    All of the pointers in the interface structure are initialized.
  980.  *
  981.  *----------------------------------------------------------------------
  982.  */
  983.  
  984. void
  985. NetDFReset(interPtr)
  986.     Net_Interface    *interPtr; /* Interface to reset. */
  987. {
  988.     register NetDFState                *statePtr;
  989.     register int            i;
  990.     unsigned short                    status;
  991.     Boolean                             test;
  992.  
  993.     statePtr = (NetDFState *) interPtr->interfaceData;
  994.     /*
  995.      * If there isn't a reset pending already, and the chip is currently
  996.      * transmitting then just set the pending flag.  With any luck
  997.      * this mechanism will prevent the chip from being reset right in
  998.      * the middle of a packet.
  999.      */
  1000.  
  1001.     if (!(statePtr->resetPending) && (statePtr->transmitting)) {
  1002.     printf("Deferring reset.\n");
  1003.     statePtr->resetPending = TRUE;
  1004.     return;
  1005.     }
  1006.     statePtr->resetPending = FALSE;
  1007.  
  1008.     /* 
  1009.      * Reset (and stop) the chip.
  1010.      */
  1011.     interPtr->flags &= ~NET_IFLAGS_RUNNING;
  1012.     /*
  1013.      * Reset the chip.  First put the chip into driver mode by setting
  1014.      * the DRIVER_MODE bit in PORT_CONTROL_B, and then set and clear
  1015.      * the RESET bit in PORT_RESET.  The chip will then run self-tests,
  1016.      * and, if the self-tests pass, should transition to UNINITIALIZED
  1017.      * in less than 30 seconds.  Otherwise it has failed the self-tests,
  1018.      * and will remain in RESETTING.
  1019.      */
  1020.     
  1021.     NET_DF_DISABLE_ALL_INT(*(statePtr->regMask));
  1022.     Mach_EmptyWriteBuffer();
  1023.  
  1024.     status = *(statePtr->regStatus);
  1025.     status = (status & NET_DF_STATUS_ADAPTER_STATE) >> 8;
  1026.  
  1027.     *(statePtr->regCtrlB) = NET_DF_CTRLB_DRIVER_MODE;
  1028.     Mach_EmptyWriteBuffer();
  1029.     *(statePtr->regReset) = NET_DF_RESET_RESET;
  1030.     Mach_EmptyWriteBuffer();
  1031.     *(statePtr->regReset) = NET_DF_CLEAR;
  1032.     Mach_EmptyWriteBuffer();
  1033.     
  1034.     NetDFAssertState(statePtr, NET_DF_STATE_RESETTING);
  1035.     printf("DEC FDDI: RESETTING -> ");
  1036.  
  1037.     statePtr->flags |= NET_DF_FLAGS_RESETTING;
  1038.     for (i = 0; i < 50000000; i++) {
  1039.     test = *(statePtr->regEvent) & NET_DF_EVENT_STATE_CHANGE;
  1040.     if (test) {
  1041.         status = *(statePtr->regStatus) & NET_DF_STATUS_ADAPTER_STATE;
  1042.         if (status == NET_DF_STATE_UNINITIALIZED) {
  1043.         printf("UNINITIALIZED -> ");
  1044.         break;
  1045.         }
  1046.     }
  1047.     }
  1048.     test = *(statePtr->regEvent) & NET_DF_EVENT_STATE_CHANGE;
  1049.     if (!test) {
  1050.     NetDFPrintRegContents(statePtr);
  1051.     panic("DEC FDDI: Adapter will not initialize!\n");
  1052.     /*
  1053.      * should read the TEST_ID field of PORT_STATUS to see which
  1054.      * self-test failed
  1055.      */
  1056.     }
  1057.     NET_DF_ENABLE_ALL_INT(*(statePtr->regMask));
  1058.     NET_DF_CLEAR_ALL_EVENTS(*(statePtr->regEvent));
  1059.  
  1060.     /*
  1061.      * Reset the COMMAND and UNSOLICITED rings before we execute commands.
  1062.      */
  1063.     statePtr->comNextPtr = statePtr->comRingPtr;
  1064.     statePtr->unsolNextDescPtr = statePtr->unsolFirstDescPtr;
  1065.     statePtr->lastUnsolCnt = 0;
  1066.  
  1067.     printf("INITIALIZED\n");
  1068.     NetDFDoInitCommand(statePtr);
  1069.     /*
  1070.      * Once the INIT command completes, we can initialize the HOST RCV,
  1071.      * SMT RCV, RMC XMT, and SMT XMT rings.
  1072.      */
  1073.     NetDFRecvInit(statePtr);
  1074.     NetDFXmitInit(statePtr);
  1075.  
  1076.     /*
  1077.      * Now that the rings are initialized, massage the adapter into the
  1078.      * RUNNING state and connect to the network.  Please please please.
  1079.      */
  1080.     status = NetDFDoModcamCommand(statePtr);
  1081.     if (status != SUCCESS) {
  1082.     goto done;
  1083.     }
  1084.     status = NetDFDoParamCommand(statePtr);
  1085.     if (status != SUCCESS) {
  1086.     goto done;
  1087.     }
  1088.     status = NetDFDoModpromCommand(statePtr);
  1089.     if (status != SUCCESS) {
  1090.     goto done;
  1091.     }
  1092.  
  1093.     NET_DF_CLEAR_ALL_EVENTS(*(statePtr->regEvent));
  1094.  
  1095. done:
  1096.     statePtr->numResets++;
  1097.     statePtr->flags &= ~NET_DF_FLAGS_RESETTING;
  1098.     if (status == SUCCESS) {
  1099.     interPtr->flags = NET_IFLAGS_RUNNING;
  1100.     } else {
  1101.     interPtr->flags &= ~NET_IFLAGS_RUNNING;
  1102.     }
  1103.     Sync_Broadcast(&statePtr->doingReset);
  1104.     return;
  1105. }
  1106.  
  1107.  
  1108. /*
  1109.  *----------------------------------------------------------------------
  1110.  *
  1111.  * NetDFRestart --
  1112.  *
  1113.  *    Reinitialize the DEC FDDI adapter.  Assumes that the
  1114.  *      interface mutex is held.
  1115.  *
  1116.  * Results:
  1117.  *    None.
  1118.  *
  1119.  * Side effects:
  1120.  *    Resets the adapter.
  1121.  *
  1122.  *----------------------------------------------------------------------
  1123.  */
  1124. void
  1125. NetDFRestart(interPtr)
  1126.     Net_Interface    *interPtr;     /* Interface to restart. */
  1127. {
  1128.  
  1129.     NetDFState    *statePtr = (NetDFState *) interPtr->interfaceData;
  1130.  
  1131.     /*
  1132.      * Drop the current packet so the sender doesn't get hung.
  1133.      */
  1134.     DFprintf("DEC FDDI: Dropping current packet.\n");
  1135.     NetDFXmitDrop(statePtr);
  1136.  
  1137.     /*
  1138.      * Reset the world.
  1139.      */
  1140.     NetDFReset(interPtr);
  1141.  
  1142.     /*
  1143.      * Restart transmission of packets.
  1144.      */
  1145.     DFprintf("DEC FDDI: Restarting transmission queue.\n");
  1146.     NetDFXmitRestart(statePtr);
  1147.  
  1148.     return;
  1149. }
  1150.  
  1151. /*
  1152.  *----------------------------------------------------------------------
  1153.  *
  1154.  * NetDFRestartCallback --
  1155.  *
  1156.  *    This routine is called by the Proc_ServerProc during the
  1157.  *    callback to reset the adapter.
  1158.  *
  1159.  * Results:
  1160.  *    None.
  1161.  *
  1162.  * Side effects:
  1163.  *    The adapter is reset.
  1164.  *
  1165.  *----------------------------------------------------------------------
  1166.  */
  1167. /*ARGSUSED*/
  1168. static void
  1169. NetDFRestartCallback(data, infoPtr)
  1170.     ClientData        data;        /* Ptr to the interface to reset. */
  1171.     Proc_CallInfo    *infoPtr;    /* Unused. */
  1172. {
  1173.     Net_DFRestart((Net_Interface *) data);
  1174. }
  1175.  
  1176. /*
  1177.  *----------------------------------------------------------------------
  1178.  *
  1179.  * Net_DFRestart --
  1180.  *
  1181.  *    This is a version of the reset routine that can be called
  1182.  *     from outside the module since it locks the mutex.
  1183.  *
  1184.  * Results:
  1185.  *    
  1186.  *
  1187.  * Side effects:
  1188.  *    None.
  1189.  *
  1190.  *----------------------------------------------------------------------
  1191.  */
  1192. void
  1193. Net_DFRestart(interPtr)
  1194.     Net_Interface    *interPtr;    /* Interface to reset. */
  1195. {
  1196.     register NetDFState *statePtr;
  1197.  
  1198.     statePtr = (NetDFState *) interPtr->interfaceData;
  1199.  
  1200.     MASTER_LOCK(&interPtr->mutex);
  1201.  
  1202.     if (statePtr->flags & NET_DF_FLAGS_RESETTING) {
  1203.     MAKE_NOTE("Restarting while restarting.  Doing nothing.");
  1204.     goto exit;
  1205.     }
  1206.  
  1207.     MAKE_NOTE("_Restarting FDDI.");
  1208.     /*
  1209.      * If we are at interrupt level we have to do a callback to reset
  1210.      * the adapter since we can't wait for the response from
  1211.      * the adapter (there may not be a current process and we can't
  1212.      * get the interrupt).
  1213.      */
  1214.     if (Mach_AtInterruptLevel()) {
  1215.     Proc_CallFunc(NetDFRestartCallback, (ClientData) interPtr, 0);
  1216.     } else {
  1217.     (void) NetDFRestart(interPtr);
  1218.     }
  1219. exit:
  1220.     MASTER_UNLOCK(&interPtr->mutex);
  1221. }
  1222.  
  1223. /*
  1224.  *----------------------------------------------------------------------
  1225.  *
  1226.  * NetDFIntr --
  1227.  *
  1228.  *    Process an interrupt from the DEC FDDI adapter.
  1229.  *
  1230.  * Results:
  1231.  *    None.
  1232.  *
  1233.  * Side effects:
  1234.  *    None.
  1235.  *
  1236.  *----------------------------------------------------------------------
  1237.  */
  1238. /* ARGSUSED */
  1239. void
  1240. NetDFIntr(interPtr, polling)
  1241.     Net_Interface    *interPtr;    /* Interface to process. */
  1242.     Boolean        polling;    /* TRUE if are being polled instead of
  1243.                      * processing an interrupt. */
  1244. {
  1245.     register NetDFState *statePtr;
  1246.     register volatile unsigned short event;
  1247.     int                 i;
  1248.     List_Links          *xmitElem;
  1249.     unsigned short      status;
  1250.     ReturnStatus        statusRcv, statusXmt;
  1251.     static Boolean      shouldNotice = FALSE;
  1252.     static Boolean      halt = FALSE;
  1253.     Boolean             test;
  1254.     unsigned short      result;
  1255.  
  1256.  
  1257.     statePtr = (NetDFState *) interPtr->interfaceData;
  1258.  
  1259.     if (statePtr->flags & NET_DF_FLAGS_RESETTING) {
  1260.     test = *(statePtr->regEvent) & NET_DF_EVENT_STATE_CHANGE;
  1261.     if (test) {
  1262.         result = *(statePtr->regStatus) & NET_DF_STATUS_ADAPTER_STATE;
  1263.         if (result == NET_DF_STATE_UNINITIALIZED) {
  1264.         /*
  1265.          * Put code here to wakeup process waiting in the
  1266.          * reset code.
  1267.          */
  1268.         } else {
  1269.         NetDFPrintRegContents(statePtr);
  1270.         panic("DEC FDDI: Adapter did not initialize during reset!\n");
  1271.         }
  1272.     } else {
  1273.         /*
  1274.          * Clear those pesky events that aren't what we are looking for.
  1275.          */
  1276.         *(statePtr->regEvent) = test;
  1277.     }
  1278.     goto exit;
  1279.     }
  1280.  
  1281. #ifdef NOTDEF
  1282. /*
  1283.  * useful for halting in the interrupt routine when debugging
  1284.  */
  1285.  
  1286.     if (halt == TRUE) {
  1287.     NET_DF_CLEAR_ALL_EVENTS(*statePtr->regEvent);
  1288.     NET_DF_DISABLE_ALL_INT(*statePtr->regMask);
  1289.     Mach_EmptyWriteBuffer();
  1290.  
  1291.     goto exit;
  1292.     }
  1293. #endif
  1294. #ifdef lint
  1295.     halt == true;
  1296. #endif
  1297.     event = *(statePtr->regEvent);
  1298.     *(statePtr->regEvent) = event;
  1299.     if (shouldNotice && !(event & NET_DF_EVENT_XMT_PKT_DONE)) {
  1300.     MAKE_NOTE("clearly missed the transmit done.");
  1301.     shouldNotice = FALSE;
  1302.     }
  1303.     status = *(statePtr->regStatus);
  1304.     DFprintf("\nDEC FDDI: NetDFIntr --->");
  1305.     /*
  1306.      * LINK_STATUS_CHANGE tells us either that we just connected
  1307.      * to the ring, or that the ring has become unavailable.
  1308.      * We are not supposed to transmit USER_LLC or USER_SMT
  1309.      * packets, although we must handle all others.
  1310.      */
  1311.     if (event & NET_DF_EVENT_LINK_STATUS_CHANGE) {
  1312.     DFprintf("DEC FDDI: Interrupt: Link status changed to 0x%x.\n",
  1313.          status & NET_DF_STATUS_LINK_STATUS);
  1314.     if ((status & NET_DF_STATUS_LINK_STATUS) == NET_DF_LINK_UNAVAILABLE) {
  1315.         printf("DEC FDDI: Link became unavailable.\n");
  1316.         halt = TRUE;
  1317.     } else {
  1318.         printf("DEC FDDI: Link now available.\n");
  1319.     }
  1320.     }
  1321.     /*
  1322.      * For the PM_PARITY_ERROR and MB_PARITY_ERROR, nothing seems
  1323.      * to happen....so do nothing.  For NXM_ERROR, the adapter
  1324.      * will have transitioned into the HALTED state.  
  1325.      */
  1326.     if (event & NET_DF_EVENT_PM_PARITY_ERROR) {
  1327.     DFprintf("DEC FDDI: Interrupt: PM parity error.\n");
  1328.     }
  1329.     if (event & NET_DF_EVENT_MB_PARITY_ERROR) {
  1330.     DFprintf("DEC FDDI: Interrupt: MB parity error.\n");
  1331.     }
  1332.     if (event & NET_DF_EVENT_NXM_ERR) {
  1333.     DFprintf("DEC FDDI: Interrupt: Non existant memory error.\n");
  1334.     }
  1335.     /*
  1336.      * Should be a rare event.
  1337.      */
  1338.     if (event & NET_DF_EVENT_FLUSH_TX) {
  1339.     DFprintf("DEC FDDI: Interrupt: Flush XMT rings requested.\n");
  1340.     }
  1341.     /*
  1342.      * The adapter has changed state.  Most likely this means that
  1343.      * we have halted for some reason.
  1344.      */
  1345.     if (event & NET_DF_EVENT_STATE_CHANGE) {
  1346.     DFprintf("DEC FDDI: Interrupt: Adapter state changed to 0x%x.\n",
  1347.          *(statePtr->regStatus) & NET_DF_STATUS_ADAPTER_STATE);
  1348.     }
  1349.     if ((*(statePtr->regStatus) & NET_DF_STATUS_ADAPTER_STATE)
  1350.     == NET_DF_STATE_HALTED) {
  1351.     printf("DEC FDDI: Adapter halted.\n");
  1352.     if (!(statePtr->flags & NET_DF_FLAGS_HALTED)) {
  1353.  
  1354. #ifdef NOTDEF
  1355.         NetDFPrintRegContents(statePtr);
  1356.         NetDFPrintErrorLog(statePtr);
  1357.     
  1358.         NET_DF_CLEAR_ALL_EVENTS(*statePtr->regEvent);
  1359.         NET_DF_DISABLE_ALL_INT(*statePtr->regMask);
  1360.         Mach_EmptyWriteBuffer();
  1361.     
  1362.         NetDFPrintDebugRing(statePtr);
  1363.         DBG_CALL;
  1364.         Mach_EmptyWriteBuffer();
  1365.         Mach_EmptyWriteBuffer();
  1366.         halt = TRUE;
  1367. #endif
  1368.         /*
  1369.          * Note that this reset does not lock the mutex.
  1370.          */
  1371.         NetDFRestart(interPtr);    
  1372.     }
  1373.     goto exit;
  1374.     }
  1375.     /*
  1376.      * An unsolicited event has arrived.  Just process it and
  1377.      * report it.
  1378.      */
  1379.     if (event & NET_DF_EVENT_UNS_POLL_DEMAND) {
  1380.     DFprintf("DEC FDDI: Interrupt: unsolicited event.\n");
  1381.     ProcessUnsolicited(statePtr);
  1382.     }
  1383.     /*
  1384.      * A command has finished.  And there was rejoicing.
  1385.      */
  1386.     if (event & NET_DF_EVENT_CMD_DONE) {
  1387.     DFprintf("DEC FDDI: Interrupt: Command done.\n");
  1388.     }
  1389.     if ((*(statePtr->regStatus) & NET_DF_STATUS_ADAPTER_STATE) 
  1390.     != NET_DF_STATE_RUNNING) {
  1391.     /*
  1392.      * If we're not in in the HALTED state and we're not in the
  1393.      * RUNNING state, then don't process any of the other events.
  1394.      */
  1395.     MAKE_NOTE("stopped processing events --> not in running state");
  1396.     goto exit;
  1397.     }
  1398.     statusRcv = statusXmt = SUCCESS;
  1399.     /*
  1400.      * We have finished transmitting a packet, so send another
  1401.      * one if there are any left.
  1402.      */
  1403.     if ((*(statePtr->regEvent) & NET_DF_EVENT_XMT_PKT_DONE)
  1404.     && !(event & NET_DF_EVENT_XMT_PKT_DONE)) {
  1405.     MAKE_NOTE("skipped a transmit done, level 1");
  1406.     shouldNotice = TRUE;
  1407.     }
  1408.     if (event & NET_DF_EVENT_XMT_PKT_DONE) {
  1409.     DFprintf("DEC FDDI: Interrupt: XMT packet done.\n");
  1410.     MAKE_NOTE("---before XMT done---");
  1411.     statusXmt = NetDFXmitDone(statePtr);
  1412.     MAKE_NOTE("---after XMT done---");
  1413.     }
  1414.     if ((*(statePtr->regStatus) & NET_DF_STATUS_ADAPTER_STATE)
  1415.     == NET_DF_STATE_HALTED) {
  1416.     MAKE_NOTE("---halted after XMT done---");
  1417.     }
  1418.     /*
  1419.      * We have received a packet, so give the contents to the lucky
  1420.      * process that's waiting for it.
  1421.      */
  1422.     if (event & NET_DF_EVENT_RCV_POLL_DEMAND) {
  1423.     DFprintf("DEC FDDI: Interrupt: RCV poll demand.\n");
  1424.     statusRcv = NetDFRecvProcess(FALSE, statePtr);
  1425.     MAKE_NOTE("---after RCV done---");
  1426.     }
  1427.     /*
  1428.      * The adapter wants us to transfer a SMT packet from the
  1429.      * SMT_XMT ring to the RMC_XMT ring.   Oblige it.
  1430.      */
  1431.     if (event & NET_DF_EVENT_SMT_XMT_POLL_DEMAND) {
  1432.     DFprintf("DEC FDDI: Interrupt: SMT XMT poll demand.\n");
  1433.  
  1434.     MAKE_NOTE("SMT XMT poll demand");
  1435.     NetDFSmtOutput(interPtr);
  1436.     }
  1437.  
  1438.     if (netDFDebug == NET_DF_DEBUG_ON) {
  1439.     i = 0;
  1440.     LIST_FORALL(statePtr->xmitList, xmitElem) {
  1441.         i++;
  1442.     }
  1443.     DFprintf("DEC FDDI: <--------------- XMT Queue: %d\n", i);
  1444.     }
  1445.     
  1446.     if (statusRcv != SUCCESS || statusXmt != SUCCESS) {
  1447.     if (statusRcv != SUCCESS) {
  1448.         MAKE_NOTE("RCV wasn't successful.");
  1449.     }
  1450.     if (statusXmt != SUCCESS) {
  1451.         MAKE_NOTE("XMT wasn't successful.");
  1452.     }
  1453.     }
  1454. exit:
  1455.     return;
  1456. }
  1457.  
  1458.  
  1459. /*
  1460.  *----------------------------------------------------------------------
  1461.  *
  1462.  * NetDFGetStats --
  1463.  *
  1464.  *    Return the statistics for the interface.
  1465.  *
  1466.  * Results:
  1467.  *    A pointer to the statistics structure.
  1468.  *
  1469.  * Side effects:
  1470.  *    None.
  1471.  *
  1472.  *----------------------------------------------------------------------
  1473.  */
  1474.  
  1475. ReturnStatus
  1476. NetDFGetStats(interPtr, statPtr)
  1477.     Net_Interface    *interPtr;        /* Current interface. */
  1478.     Net_Stats        *statPtr;        /* Statistics to return. */
  1479. {
  1480.     NetDFState *statePtr = (NetDFState *) interPtr->interfaceData;
  1481.  
  1482.     MASTER_LOCK(&interPtr->mutex);
  1483.  
  1484.     if (statePtr->flags & NET_DF_FLAGS_RESETTING) {
  1485.     MAKE_NOTE("Process waiting in NetDFIOControl while resetting.\n");
  1486.     do {
  1487.         Sync_MasterWait(&statePtr->doingReset, &interPtr->mutex, FALSE);
  1488.     } while (statePtr->flags & NET_DF_FLAGS_RESETTING);
  1489.     }
  1490.  
  1491.     MAKE_NOTE("Returning FDDI stats.");
  1492.     statPtr->fddi = statePtr->stats;
  1493.  
  1494.     MASTER_UNLOCK(&interPtr->mutex);
  1495.     return SUCCESS;
  1496. }
  1497.  
  1498.  
  1499. /*
  1500.  *----------------------------------------------------------------------
  1501.  *
  1502.  * NetDFIOControl --
  1503.  *
  1504.  *    Perform ioctls for the adapter.  Right now we don't support any.
  1505.  *
  1506.  * Results:
  1507.  *    DEV_INVALID_ARG
  1508.  *
  1509.  * Side effects:
  1510.  *    None.
  1511.  *
  1512.  *----------------------------------------------------------------------
  1513.  */
  1514. /*ARGSUSED*/
  1515. ReturnStatus
  1516. NetDFIOControl(interPtr, ioctlPtr, replyPtr)
  1517.     Net_Interface *interPtr;    /* Interface on which to perform ioctl. */
  1518.     Fs_IOCParam *ioctlPtr;    /* Standard I/O Control parameter block */
  1519.     Fs_IOReply *replyPtr;    /* Size of outBuffer and returned signal */
  1520. {
  1521.     register NetDFState *statePtr;
  1522.     ReturnStatus status;
  1523.  
  1524.     statePtr = (NetDFState *)interPtr->interfaceData;
  1525.  
  1526.     DFprintf("NetDFIOControl: command = %d\n", ioctlPtr->command);
  1527.     if ((ioctlPtr->command & ~0xffff) != IOC_FDDI) {
  1528.     return DEV_INVALID_ARG;
  1529.     }
  1530.  
  1531.     MASTER_LOCK(&interPtr->mutex);
  1532.  
  1533.     if (statePtr->flags & NET_DF_FLAGS_RESETTING) {
  1534.     MAKE_NOTE("Process waiting in NetDFIOControl while resetting.\n");
  1535.     do {
  1536.         Sync_MasterWait(&statePtr->doingReset, &interPtr->mutex, FALSE);
  1537.     } while (statePtr->flags & NET_DF_FLAGS_RESETTING);
  1538.     }
  1539.  
  1540.     status = SUCCESS;
  1541.     switch(ioctlPtr->command) {
  1542.     case IOC_FDDI_RESET:
  1543.     MASTER_UNLOCK(&interPtr->mutex);
  1544.     statePtr->flags &= ~NET_DF_FLAGS_HALTED;
  1545.     Net_DFRestart(interPtr);
  1546.     MASTER_LOCK(&interPtr->mutex);
  1547.     status = SUCCESS;
  1548.     break;
  1549.     case IOC_FDDI_DEBUG:
  1550.     if (netDFDebug == NET_DF_DEBUG_ON) {
  1551.         printf("DEC FDDI: Debug turned off.\n");
  1552.         netDFDebug = NET_DF_DEBUG_OFF;
  1553.     } else {
  1554.         printf("DEC FDDI: Debug turned on.\n");
  1555.         netDFDebug = NET_DF_DEBUG_ON;
  1556.     }
  1557.     break;
  1558.     case IOC_FDDI_REG_CONTENTS: {
  1559.     Dev_FDDIRegContents *regContentsPtr;
  1560.     
  1561.     regContentsPtr = (Dev_FDDIRegContents *)ioctlPtr->outBuffer;
  1562.     if (regContentsPtr == NULL) {
  1563.         status = FAILURE;
  1564.         goto exit;
  1565.     }
  1566.     regContentsPtr->regReset = *(statePtr->regReset);
  1567.     regContentsPtr->regCtrlA = *(statePtr->regCtrlA);
  1568.     regContentsPtr->regCtrlB = *(statePtr->regCtrlB);
  1569.     regContentsPtr->regStatus = *(statePtr->regStatus);
  1570.     regContentsPtr->regEvent = *(statePtr->regEvent);
  1571.     regContentsPtr->regMask = *(statePtr->regMask);
  1572.     break;
  1573.     }
  1574.     case IOC_FDDI_ERR_LOG: {
  1575.     Dev_FDDIErrLog *errLogPtr;
  1576.  
  1577.     errLogPtr = (Dev_FDDIErrLog *)ioctlPtr->outBuffer;
  1578.     if (errLogPtr == NULL) {
  1579.         status = FAILURE;
  1580.         goto exit;
  1581.     }
  1582.     errLogPtr->internal = *(statePtr->errLogPtr +
  1583.                 NET_DF_MACH_ERR_INTERNAL_OFFSET);
  1584.     errLogPtr->external = *(statePtr->errLogPtr +
  1585.                 NET_DF_MACH_ERR_EXTERNAL_OFFSET);
  1586.     break;
  1587.     }
  1588.     case IOC_FDDI_SEND_PACKET: {
  1589.     Dev_FDDISendPacket *packetPtr;
  1590.     Net_FDDIHdr        *fddiHdrPtr;
  1591.     Net_ScatterGather  *scatterPtr;
  1592.  
  1593.     packetPtr = (Dev_FDDISendPacket *)ioctlPtr->inBuffer;
  1594.     if (packetPtr == NULL) {
  1595.         status = FAILURE;
  1596.         goto exit;
  1597.     }
  1598.     fddiHdrPtr = &statePtr->headerArray[statePtr->scatterIndex];
  1599.     scatterPtr = &statePtr->scatterArray[statePtr->scatterIndex];
  1600.     IncScatterIndex(statePtr);
  1601.  
  1602.     fddiHdrPtr->prh[0] = NET_DF_PRH0;
  1603.     fddiHdrPtr->prh[1] = NET_DF_PRH1;
  1604.     fddiHdrPtr->prh[2] = NET_DF_PRH2;
  1605.     fddiHdrPtr->frameControl = NET_DF_FRAME_HOST_LLC;
  1606.     NET_FDDI_ADDR_COPY(packetPtr->dest, fddiHdrPtr->dest);
  1607.     
  1608.     scatterPtr->bufAddr = packetPtr->buffer;
  1609.     scatterPtr->length = packetPtr->length;
  1610.     scatterPtr->mutexPtr = NULL;
  1611.     scatterPtr->done = FALSE;
  1612.  
  1613.     /*
  1614.      * NetDFOutput locks the mutex.
  1615.      */
  1616.     MASTER_UNLOCK(&interPtr->mutex);
  1617.     status = NetDFOutput(interPtr, fddiHdrPtr, scatterPtr, 1, FALSE, NIL);
  1618.     MASTER_LOCK(&interPtr->mutex);
  1619.  
  1620.     break;
  1621.     }
  1622.     case IOC_FDDI_FLUSH_XMT_Q: {
  1623.     printf("DEC FDDI: Dropping current packet.\n");
  1624.     NetDFXmitDrop(statePtr);
  1625.     printf("DEC FDDI: Flushing transmit queue.\n");
  1626.     NetDFXmitFlushQ(statePtr);
  1627.     break;
  1628.     }
  1629.     case IOC_FDDI_ADDRESS: {
  1630.     Dev_FDDILinkAddr *infoPtr;
  1631.  
  1632.     infoPtr = (Dev_FDDILinkAddr *)ioctlPtr->outBuffer;
  1633.     if (infoPtr == NULL) {
  1634.         status = FAILURE;
  1635.         goto exit;
  1636.     }
  1637.     NET_FDDI_ADDR_COPY(statePtr->fddiAddress, infoPtr->source);
  1638.     break;
  1639.     }
  1640.     case IOC_FDDI_RPC_ECHO: {
  1641.     Dev_FDDIRpcEcho       *echoPtr;
  1642.     Dev_FDDIRpcEchoReturn *returnPtr;
  1643.     char                  *bufPtr;
  1644.  
  1645.     echoPtr = (Dev_FDDIRpcEcho *)ioctlPtr->inBuffer;
  1646.     if (echoPtr == NULL || echoPtr == (Dev_FDDIRpcEcho *)NULL) {
  1647.         status = FAILURE;
  1648.         goto exit;
  1649.     }
  1650.     returnPtr = (Dev_FDDIRpcEchoReturn *)ioctlPtr->outBuffer;
  1651.     if (returnPtr == NULL || returnPtr == (Dev_FDDIRpcEchoReturn *)NULL) {
  1652.         status = FAILURE;
  1653.         goto exit;
  1654.     }
  1655.     bufPtr = (char *)malloc(echoPtr->packetSize);
  1656.     if (echoPtr->printSyslog == TRUE) {
  1657.         status = Rpc_EchoTest(echoPtr->serverID, echoPtr->numEchoes,
  1658.                   echoPtr->packetSize, bufPtr, bufPtr, 
  1659.                   (Time *)NIL);
  1660.     } else {
  1661.         status = Rpc_EchoTest(echoPtr->serverID, echoPtr->numEchoes,
  1662.                   echoPtr->packetSize, bufPtr, bufPtr, 
  1663.                   &returnPtr->rpcTime);
  1664.     }
  1665.     free(bufPtr);
  1666.     break;
  1667.     }
  1668.     case IOC_FDDI_HALT: {
  1669.     statePtr->flags |= NET_DF_FLAGS_HALTED;
  1670.     *(statePtr->regCtrlA) |= NET_DF_CTRLA_HALT;
  1671.     break;
  1672.     }
  1673.     case IOC_FDDI_STATS: {
  1674.     Dev_FDDIStats *statsPtr;
  1675.  
  1676.     statsPtr = (Dev_FDDIStats *)ioctlPtr->outBuffer;
  1677.     if (statsPtr == NULL || statsPtr == (Dev_FDDIStats *)NIL) {
  1678.         status = DEV_INVALID_ARG;
  1679.         goto exit;
  1680.     }
  1681.     bcopy((Address)&statePtr->stats, (Address)statsPtr,
  1682.           sizeof(Dev_FDDIStats));
  1683.     break;
  1684.     }
  1685.     default:
  1686.     printf("NetDFIOControl: unknown ioctl 0x%x\n", ioctlPtr->command);
  1687.     }
  1688.     
  1689. exit:
  1690.     MASTER_UNLOCK(&interPtr->mutex);
  1691.     return status;
  1692. }
  1693.